<script setup lang="ts">
import { ref, onMounted, watch, computed, onBeforeUnmount, nextTick } from 'vue'
import * as echarts from 'echarts/core'
import { LineChart } from 'echarts/charts'
import type { LineSeriesOption } from 'echarts/charts'
import {
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
  ToolboxComponent,
  DataZoomComponent
} from 'echarts/components'
import type {
  TitleComponentOption,
  TooltipComponentOption,
  GridComponentOption,
  LegendComponentOption,
  ToolboxComponentOption,
  DataZoomComponentOption
} from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers'
import type { EChartsType } from 'echarts/core'

// 定义图表选项类型
type ECOption = echarts.ComposeOption<
  | LineSeriesOption
  | TitleComponentOption
  | TooltipComponentOption
  | GridComponentOption
  | LegendComponentOption
  | ToolboxComponentOption
  | DataZoomComponentOption
>

// 注册必要的组件
echarts.use([
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LineChart,
  LegendComponent,
  ToolboxComponent,
  DataZoomComponent,
  CanvasRenderer
])

const props = defineProps({
  data: {
    type: Array,
    required: true,
    default: () => []
  },
  title: {
    type: String,
    default: '热点话题情感趋势'
  },
  height: {
    type: String,
    default: '600px'
  },
  theme: {
    type: String,
    default: ''
  }
})

const chartRef = ref<HTMLElement | null>(null)
const chart = ref<EChartsType | null>(null)
let resizeObserver: ResizeObserver | null = null

interface HeatmapItem {
  id: number;
  topic: string;
  time: string;
  sentiment_value: number;
}

// 处理数据，转换为折线图需要的格式
const processData = (rawData: HeatmapItem[]) => {
  if (!rawData || rawData.length === 0) return { series: [], times: [] }
  
  // 获取所有话题
  const topics = [...new Set(rawData.map(item => item.topic))]
  
  // 如果话题太多，只取前6个
  const limitedTopics = topics.length > 6 ? topics.slice(0, 6) : topics
  
  // 按小时聚合时间
  const times = Array.from({ length: 24 }, (_, i) => `${i.toString().padStart(2, '0')}:00`)
  
  // 为每个话题生成一条折线
  const series = limitedTopics.map((topic, index) => {
    const data = times.map(time => {
      // 过滤出当前话题和时间的数据
      const timeHour = parseInt(time.split(':')[0])
      const filteredData = rawData.filter(item => {
        const itemHour = new Date(item.time).getHours()
        return item.topic === topic && itemHour === timeHour
      })
      
      // 计算情感均值
      let sentimentSum = 0
      let count = 0
      
      filteredData.forEach(item => {
        sentimentSum += item.sentiment_value
        count++
      })
      
      const avgSentiment = count > 0 ? sentimentSum / count : null
      
      return avgSentiment !== null ? parseFloat(avgSentiment.toFixed(2)) : '-'
    })
    
    // 设置更加明显不同的线条样式
    const lineTypes = ['solid', 'dashed', 'dotted']
    const symbolTypes = ['circle', 'rect', 'triangle', 'diamond', 'pin', 'arrow']
    
    return {
      name: topic,
      type: 'line',
      data: data,
      smooth: true,
      symbol: symbolTypes[index % symbolTypes.length],
      symbolSize: 10, // 增大标记点尺寸
      emphasis: {
        focus: 'series',
        lineStyle: {
          width: 6
        }
      },
      lineStyle: {
        width: 4, // 增加线条宽度
        type: lineTypes[index % lineTypes.length]
      }
    } as LineSeriesOption
  })
  
  return {
    series,
    times
  }
}

// 计算处理后的数据
const chartData = computed(() => {
  return processData(props.data as HeatmapItem[])
})

// 初始化图表
const initChart = () => {
  if (!chartRef.value) return
  
  // 销毁之前的实例
  if (chart.value) {
    chart.value.dispose()
  }
  
  // 创建图表实例
  nextTick(() => {
    if (chartRef.value) {
      chart.value = echarts.init(chartRef.value, props.theme)
      
      // 使用ResizeObserver监听容器大小变化
      if (resizeObserver) {
        resizeObserver.disconnect()
      }
      
      resizeObserver = new ResizeObserver(() => {
        if (chart.value) {
          try {
            chart.value.resize()
          } catch (e) {
            console.error('图表调整大小失败:', e)
          }
        }
      })
      
      if (chartRef.value) {
        resizeObserver.observe(chartRef.value)
      }
      
      // 更新图表
      updateChart()
      
      // 确保图表在DOM完全渲染后调整大小
      setTimeout(() => {
        if (chart.value) {
          chart.value.resize()
        }
      }, 200)
    }
  })
}

// 更新图表
const updateChart = () => {
  if (!chart.value) return
  
  try {
    const { series, times } = chartData.value
    
    // 定义更加鲜明对比的颜色方案，确保每条线都有显著不同的颜色
    const colorPalette = [
      '#FF0000', // 纯红色
      '#0000FF', // 纯蓝色
      '#00FF00', // 纯绿色
      '#FF00FF', // 洋红色
      '#FFFF00', // 黄色
      '#00FFFF', // 青色
      '#000000', // 黑色
      '#FF8000', // 橙色
      '#8000FF', // 紫色
      '#0080FF'  // 天蓝色
    ]
    
    const option: ECOption = {
      color: colorPalette,
      title: {
        text: props.title,
        left: 'center',
        top: 10,
        textStyle: {
          fontSize: 16,
          fontWeight: 'normal'
        }
      },
      tooltip: {
        trigger: 'axis',
        formatter: function(params: any) {
          let result = `<div style="padding: 3px;"><strong>${params[0].axisValue}</strong></div>`
          params.forEach((param: any) => {
            if (param.value !== null) {
              let color = '#909399'
              let sentimentType = '中性'
              
              if (param.value > 0.3) {
                color = '#67C23A'
                sentimentType = '正面'
              } else if (param.value < -0.3) {
                color = '#F56C6C'
                sentimentType = '负面'
              }
              
              result += `
                <div style="display: flex; align-items: center; padding: 3px;">
                  <span style="display: inline-block; width: 10px; height: 10px; background: ${param.color}; margin-right: 5px;"></span>
                  <span style="margin-right: 15px;">${param.seriesName}:</span>
                  <span style="color: ${color}; font-weight: bold;">${param.value} (${sentimentType})</span>
                </div>
              `
            }
          })
          return result
        },
        backgroundColor: 'rgba(255, 255, 255, 0.95)',
        borderColor: '#eee',
        borderWidth: 1,
        padding: 10,
        textStyle: {
          color: '#333',
          fontSize: 12
        }
      },
      legend: {
        data: series.map(item => item.name),
        top: 40,
        type: 'scroll',
        pageIconSize: 12,
        tooltip: {
          show: true
        }
      } as LegendComponentOption,
      grid: {
        top: 90,
        left: '5%',
        right: '5%',
        bottom: 60,
        containLabel: true
      },
      toolbox: {
        feature: {
          saveAsImage: { title: '保存为图片' },
          dataView: { title: '数据视图', lang: ['数据视图', '关闭', '刷新'] },
          restore: { title: '还原' },
          dataZoom: { title: { zoom: '区域缩放', back: '还原缩放' } }
        },
        right: '10px',
        top: '10px'
      },
      dataZoom: [
        {
          type: 'slider',
          show: true,
          xAxisIndex: [0],
          start: 0,
          end: 100,
          height: 20,
          bottom: 10,
          borderColor: 'transparent',
          backgroundColor: '#f5f5f5',
          fillerColor: 'rgba(67, 142, 219, 0.2)',
          handleStyle: {
            color: '#409EFF'
          }
        },
        {
          type: 'inside',
          xAxisIndex: [0],
          start: 0,
          end: 100
        }
      ],
      xAxis: {
        type: 'category',
        data: times,
        boundaryGap: false,
        axisLine: {
          lineStyle: {
            color: '#ddd'
          }
        },
        axisLabel: {
          formatter: '{value}',
          color: '#666',
          interval: 2
        },
        axisTick: {
          show: false
        },
        splitLine: {
          show: true,
          lineStyle: {
            color: ['#f5f5f5'],
            type: 'dashed'
          }
        }
      },
      yAxis: {
        type: 'value',
        name: '情感值',
        min: -1,
        max: 1,
        interval: 0.2,
        axisLabel: {
          formatter: function(value: number) {
            if (value > 0) return `+${value.toFixed(1)}`
            return value.toFixed(1)
          },
          color: '#666'
        },
        axisLine: {
          show: true,
          lineStyle: {
            color: '#ddd'
          }
        },
        axisTick: {
          show: false
        },
        splitLine: {
          show: true,
          lineStyle: {
            color: ['#f5f5f5']
          }
        },
        splitArea: {
          show: true,
          areaStyle: {
            color: ['rgba(250,250,250,0.3)', 'rgba(245,245,245,0.3)']
          }
        }
      },
      visualMap: {
        show: false,
        pieces: [
          {
            gt: 0.3,
            lte: 1,
            color: '#67C23A'
          },
          {
            gt: -0.3,
            lte: 0.3,
            color: '#909399'
          },
          {
            gt: -1,
            lte: -0.3,
            color: '#F56C6C'
          }
        ],
        outOfRange: {
          color: '#909399'
        }
      },
      series: series
    }
    
    chart.value.setOption(option)
  } catch (e) {
    console.error('图表更新失败:', e)
  }
}

// 监听数据变化
watch(() => props.data, () => {
  updateChart()
}, { deep: true })

// 监听容器大小变化
watch(() => props.height, () => {
  nextTick(() => {
    chart.value && chart.value.resize()
  })
})

onMounted(() => {
  initChart()
})

onBeforeUnmount(() => {
  // 清理资源
  if (resizeObserver) {
    resizeObserver.disconnect()
    resizeObserver = null
  }
  
  if (chart.value) {
    chart.value.dispose()
    chart.value = null
  }
})
</script>

<template>
  <div class="sentiment-topic-trend-chart" :style="{ height: props.height }">
    <div ref="chartRef" class="chart-container"></div>
  </div>
</template>

<style scoped>
.sentiment-topic-trend-chart {
  width: 100%;
  position: relative;
  overflow: hidden;
}

.chart-container {
  width: 100%;
  height: 100%;
  min-height: 500px;
}

@media screen and (max-width: 1200px) {
  .chart-container {
    min-height: 400px;
  }
}

@media screen and (max-width: 768px) {
  .chart-container {
    min-height: 350px;
  }
}
</style> 